package nancal.mp.service

import io.kubernetes.client.openapi.ApiClient
import io.kubernetes.client.openapi.apis.NetworkingV1Api
import io.kubernetes.client.openapi.models.*
import nancal.mp.util.tidyK8sYaml
import nbcp.base.comm.JsonMap
import nbcp.base.extend.FromJson
import nbcp.base.extend.ToYaml
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service

@Service
class K8sIngressService : K8sBaseService() {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    fun addVPath(
        targetEnv: String,
        namespace: String,
        ingressName: String,
        ingressHost: String,
        vPath: String,
        targetService: String
    ) {
        addVPath(getK8sClient(targetEnv), namespace, ingressName, ingressHost, vPath, targetService)
    }


    fun getAddVPath(
        client: ApiClient,
        namespace: String,
        ingressName: String,
        ingressHost: String,
        vPath: String,
        targetService: String
    ): V1Ingress? {
        if (vPath.isNullOrEmpty()) {
            return null
        }

        var networkApi = NetworkingV1Api(client);

        var ingress = networkApi.readNamespacedIngress(ingressName, namespace).execute()

        if (ingress == null || ingress.status == null) {
            throw RuntimeException("缺少 ${ingressName} 的 Ingress 应用路由")
        }

        val rules = ingress.spec!!.rules
        if (rules == null || rules!!.size == 0) {
            throw RuntimeException("${ingressName} 缺少 spec.rules 节点")
        }

        val rule = rules.filter { it: V1IngressRule? -> it!!.host == ingressHost }.firstOrNull()
            ?: throw RuntimeException("${ingressName} 节点找不到 spec.rules.host:${ingressHost} 节点")

        var paths = rule.http!!.paths
        if (paths == null) {
            paths = ArrayList()
            rule.http!!.paths = paths
        }


        if (paths.stream().anyMatch { it: V1HTTPIngressPath -> it.path == vPath }) {
            return null;
        }
        /*

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  labels:
    ingress-controller: alb
  name: demo-test
  namespace: default
spec:
  ingressClassName: alb
  rules:
    - host: foo.bar.com
      http:
        paths:
          - backend:
              service:
                name: nginx-demo-svc
                port:
                  number: 80
            path: /
            pathType: Prefix
         */

        val path = V1HTTPIngressPath()
        val back = V1IngressBackend()
        var port = V1ServiceBackendPort();
        port.number = 80
        val service = V1IngressServiceBackend()
        service.name = targetService
        service.port(port)
        back.setService(service)
        path.pathType = "Prefix"
        path.setPath(vPath)
        path.backend = back

        paths.add(path)

        return ingress
    }

    fun addVPath(
        client: ApiClient,
        namespace: String,
        ingressName: String,
        ingressHost: String,
        vPath: String,
        targetService: String
    ) {
        var ingress = getAddVPath(client, namespace, ingressName, ingressHost, vPath, targetService)

        if (ingress == null) {
            return;
        }

        var networkApi = NetworkingV1Api(client);

        try {
            networkApi.replaceNamespacedIngress(
                ingressName,
                namespace,
                ingress
            ).execute()
        } catch (e: Exception) {
            logger.error(
                """应用Ingress报错:${e.message}
${ingress.toJson().FromJson<JsonMap>()!!.tidyK8sYaml().ToYaml()}
"""
            )
            throw e;
        }
    }

}